import 'package:flutter_menu/data/obx_store.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_menu/model/login_model.dart';
import 'package:flutter_menu/model/product_model.dart';
import 'package:flutter_menu/model/sellout_model.dart';
import 'package:flutter_menu/model/shope_model.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:objectbox/objectbox.dart';

import '../objectbox.g.dart';
import 'category_model.dart';
import 'formula_model.dart';
import 'material_model.dart';

part 'menu_model.g.dart';

@JsonSerializable()
class SyncResModel {
  static const String TYPE_SHOP_INFO = "shopInfo";
  static const String TYPE_USER_LIST = "userList";

  ///菜品分类信息
  // List<CategoryModel>? categoryList;

  ///自定义菜单信息
  List<CustomMenuModel>? customMenuList;

  ///电子菜单信息
  List<ElectronicMenuModel>? electronicMenuList;

  ///菜品配方信息
  List<FormulaModel>? formulaList;

  ///原料库存信息
  List<MaterialDeptStockModel>? materialDeptStockList;

  ///原料信息
  List<MaterialModel>? materialList;

  ///选项原料信息
  List<OptionMaterialModel>? optionMaterialList;

  ///菜品信息
  List<ProductModel>? productList;

  ///店铺信息
  ShopModel? shopInfo;

  ///房台信息
  List<ShopTableInfoModel>? shopTableInfo;

  ///员工信息
  List<UserModel>? userList;

  ///部门信息
  List<DeptModel>? deptList;

  ///估清数据
  List<SelloutModel>? selloutList;

  SyncResModel();

  factory SyncResModel.fromJson(Map<String, dynamic> json) =>
      _$SyncResModelFromJson(json);

  Map<String, dynamic> toJson() => _$SyncResModelToJson(this);

  void update(Store store,{int? time }) {
    time = time ?? DateTime.now().microsecondsSinceEpoch;
    shopInfo?.update(store, time);
    _update(store,customMenuList,time);
    _update(store,materialList,time);
    _update(store,userList,time );
    _update(store,formulaList,time);
    _update(store,optionMaterialList,time);
    _update(store,materialDeptStockList,time);
    _update(store,productList,time);
    _update(store,shopTableInfo,time);
    _update(store,electronicMenuList,time);
    _update(store,deptList,time);
    _update(store,selloutList,time);
    store.removeAll(time: time);
  }

  void upUserList(Store store,{int? time }){
    time = time ?? DateTime.now().microsecondsSinceEpoch;
    _update(store,userList,time );
    var box =  store.box<UserModel>();
    box.removeByTimeStamp(UserModel_.updateTime, time);
  }

  void _update<T extends IEntity>(Store store, List<T>? data, int time) {
    if (data == null) return;
    for (T t in data) {
      t.update(store, time);
    }
  }
}

@Entity()
@JsonSerializable()
class CustomMenuModel with IEntity{
  @Id()
  int obxId;

  ///分类列表
  @JsonKey(
      fromJson: CustomMenuListCategoryList.toManyFromJson,
      toJson: CustomMenuListCategoryList.toManyJson)
  ToMany<CustomMenuListCategoryList> categoryList =
      ToMany<CustomMenuListCategoryList>();

  ///菜单名称
  String? menuName;

  ///菜单适用场景：1POS下单，2扫码下单，3服务员下单，4自建外卖平台下单
  int? menuScene;

  ///菜单状态：0停用，1启用
  int? menuStatus;

  ///菜单类型：1快餐，2正餐，3外卖
  int? menuType;

  ///适用房台列表(如果是正餐菜单，会有适用房台)
  List<String>? tableList;

  ///菜单uuid
  String? uuid;

  @override
  int updateTime ;

  CustomMenuModel({
    this.obxId = 0,
    this.updateTime = 0,
    this.menuName,
    this.menuScene,
    this.menuStatus,
    this.menuType,
    this.tableList,
    this.uuid,
  });

  factory CustomMenuModel.fromJson(Map<String, dynamic> json) =>
      _$CustomMenuModelFromJson(json);

  Map<String, dynamic> toJson() => _$CustomMenuModelToJson(this);

  static ToOne<CustomMenuModel> toOneFromJson(Map<String, dynamic> json) =>
      ToOne(target: CustomMenuModel.fromJson(json));

  static Map<String, dynamic>? toOneJson(ToOne<CustomMenuModel> s) =>
      s.target != null ? _$CustomMenuModelToJson(s.target!) : {};

  static ToMany<CustomMenuModel> toManyFromJson(List<dynamic>? json) =>
      ToMany(items: json?.map((e) => CustomMenuModel.fromJson(e)).toList());

  static List<Map<String, dynamic>>? toManyJson(ToMany<CustomMenuModel>? s) =>
      s?.toList().map((e) => e.toJson()).toList();

  @override
  int update(Store store,int? time) {
    updateTime = time ?? updateTime;
    for(CustomMenuListCategoryList e in categoryList){
      e.obxId = e.update(store, time);
    }
    var box = store.box<CustomMenuModel>();
    return box.update(this, CustomMenuModel_.uuid, uuid);
  }
}

@Entity()
@JsonSerializable()
class CustomMenuListCategoryList with IEntity {
  @Id()
  int obxId;

  ///分类的名称
  String? categoryName;

  ///分类的菜品列表
  @JsonKey(
      fromJson: CategoryListProductList.toManyFromJson,
      toJson: CategoryListProductList.toManyJson)
  ToMany<CategoryListProductList> productList =
      ToMany<CategoryListProductList>();

  ///第二语言
  String? secondName;

  ///分类的排序字段
  int? sort;

  ///分类的供应时段列表
  @JsonKey(fromJson: SupplyTime.toManyFromJson, toJson: SupplyTime.toManyJson)
  ToMany<SupplyTime> supplyTime = ToMany<SupplyTime>();

  ///分类的uuid
  String? uuid;

  @override
  int updateTime ;

  CustomMenuListCategoryList({
    this.obxId = 0,
    this.updateTime = 0,
    this.categoryName,
    this.secondName,
    this.sort,
    this.uuid,
  });

  factory CustomMenuListCategoryList.fromJson(Map<String, dynamic> json) =>
      _$CustomMenuListCategoryListFromJson(json);

  Map<String, dynamic> toJson() => _$CustomMenuListCategoryListToJson(this);

  static ToOne<CustomMenuListCategoryList> toOneFromJson(
          Map<String, dynamic> json) =>
      ToOne(target: CustomMenuListCategoryList.fromJson(json));

  static Map<String, dynamic>? toOneJson(ToOne<CustomMenuListCategoryList> s) =>
      s.target != null ? _$CustomMenuListCategoryListToJson(s.target!) : {};

  static ToMany<CustomMenuListCategoryList> toManyFromJson(
          List<dynamic>? json) =>
      ToMany(
          items: json
              ?.map((e) => CustomMenuListCategoryList.fromJson(e))
              .toList());

  static List<Map<String, dynamic>>? toManyJson(
          ToMany<CustomMenuListCategoryList>? s) =>
      s?.toList().map((e) => e.toJson()).toList();

  @override
  int update(Store store,int? time) {
    updateTime = time ?? updateTime;
    var box = store.box<CustomMenuListCategoryList>();
    productList.forEach((e)=> e.obxId = e.update(store,time));
    supplyTime.forEach((e)=> e.obxId = e.update(store,time));
    return box.update(this, CustomMenuListCategoryList_.uuid, uuid);
  }

  @override
  String toString() {
    return 'CustomMenuListCategoryList{obxId: $obxId, categoryName: $categoryName, productList: $productList, secondName: $secondName, sort: $sort, supplyTime: $supplyTime, uuid: $uuid, updateTime: $updateTime}';
  }
}

@Entity()
@JsonSerializable()
class CategoryListProductList with IEntity{
  @Id()
  int obxId;

  ///该菜品下的规格列表
  @JsonKey(fromJson: DishList.toManyFromJson, toJson: DishList.toManyJson)
  ToMany<DishList> dishList = ToMany<DishList>();

  ///类型 0菜品 1套餐
  int? productType;

  ///菜品uuid
  String? productUuid;

  ///菜品排序
  int? sort;

  @override
  int updateTime ;

  ///图片名称
  @Transient()
  String? imageName;

  ///图片地址
  @Transient()
  String? imageUrl;

  ///热点区域
  @Transient()
  String? hotZone;

  ///读取菜单的品名、价格和添加按钮 0否 1是
  @Transient()
  int? isRead;

  CategoryListProductList({
    this.obxId = 0,
    this.updateTime = 0,
    this.productType,
    this.productUuid,
    this.sort,
  });

  factory CategoryListProductList.fromJson(Map<String, dynamic> json) =>
      _$CategoryListProductListFromJson(json);

  Map<String, dynamic> toJson() => _$CategoryListProductListToJson(this);

  static ToOne<CategoryListProductList> toOneFromJson(
          Map<String, dynamic> json) =>
      ToOne(target: CategoryListProductList.fromJson(json));

  static Map<String, dynamic>? toOneJson(ToOne<CategoryListProductList> s) =>
      s.target != null ? _$CategoryListProductListToJson(s.target!) : {};

  static ToMany<CategoryListProductList> toManyFromJson(List<dynamic>? json) =>
      ToMany(
          items:
              json?.map((e) => CategoryListProductList.fromJson(e)).toList());

  static List<Map<String, dynamic>>? toManyJson(
          ToMany<CategoryListProductList>? s) =>
      s?.toList().map((e) => e.toJson()).toList();

  @override
  int update (Store store,int? time) {
    updateTime = time ?? updateTime;
    var box = store.box<CategoryListProductList>();
    dishList.forEach((e)=> e.obxId = e.update(store,time));
    return box.put(this);
  }

  double? getLowestPrice() {
    if (dishList.isEmpty) {
      return null; // 如果列表为空，返回 null
    }

    // 使用 reduce 比较，返回 customPrice 最小的 DishList 项
    final lowestDish = dishList.reduce((current, next) {
      debugPrint("getLowestPrice: $current $next");
      return (current.customPrice ?? 0) <
          (next.customPrice ?? 0)
          ? current
          : next;
    });

    return lowestDish.customPrice;
  }

  bool isPackage() {
    return productType == 1;
  }

  bool isMultiSpec() {
    return dishList.length > 1 && !isPackage();
  }

  @override
  String toString() {
    return 'CategoryListProductList{obxId: $obxId, productUuid: $productUuid, productType: $productType, sort: $sort, imageName: $imageName, imageUrl: $imageUrl, hotZone: $hotZone, isRead: $isRead, dishList: $dishList}';
  }
}

@Entity()
@JsonSerializable()
class ElectronicMenuModel with IEntity{
  @Id()
  int obxId;

  ///电子菜单主键id
  String? id;

  ///电子菜单名称
  String? name;

  ///适用自定义菜单的uuid
  String? customMenuUuid;

  ///设备类型 0 三星A7（800*1340; 1 三星A9（1200*1920); 2 ipad（1640*2360）
  String? deviceType;

  ///自定义菜单的菜品规格表的uuid
  String? dishUuid;

  ///读取菜单的品名、价格和添加按钮 0否 1是
  int? isRead;

  ///电子菜单菜品信息
  @JsonKey(
      fromJson: ElectronicMenuProduct.toManyFromJson,
      toJson: ElectronicMenuProduct.toManyJson)
  ToMany<ElectronicMenuProduct> productList = ToMany<ElectronicMenuProduct>();

  ElectronicMenuModel({
    this.obxId = 0,
    this.updateTime = 0,
    this.customMenuUuid,
    this.deviceType,
    this.dishUuid,
    this.id,
    this.isRead,
    this.name,
  });

  factory ElectronicMenuModel.fromJson(Map<String, dynamic> json) =>
      _$ElectronicMenuModelFromJson(json);

  Map<String, dynamic> toJson() => _$ElectronicMenuModelToJson(this);

  static ToOne<ElectronicMenuModel> toOneFromJson(Map<String, dynamic> json) =>
      ToOne(target: ElectronicMenuModel.fromJson(json));

  static Map<String, dynamic>? toOneJson(ToOne<ElectronicMenuModel> s) =>
      s.target != null ? _$ElectronicMenuModelToJson(s.target!) : {};

  static ToMany<ElectronicMenuModel> toManyFromJson(List<dynamic>? json) =>
      ToMany(items: json?.map((e) => ElectronicMenuModel.fromJson(e)).toList());

  static List<Map<String, dynamic>>? toManyJson(
          ToMany<ElectronicMenuModel>? s) =>
      s?.toList().map((e) => e.toJson()).toList();

  @override
  int updateTime;

  @override
  int update(Store store,int? time) {
    updateTime = time?? updateTime;
    productList.forEach((e)=> e.obxId = e.update(store,time));
    var box =  store.box<ElectronicMenuModel>();
    return box.update(this, ElectronicMenuModel_.id, id);
  }
}

@Entity()
@JsonSerializable()
class ElectronicMenuProduct with IEntity{
  @Id()
  int obxId;

  ///菜品uuid
  String? productUuid;

  ///自定义菜单的菜品规格表的uuid
  String? dishUuid;

  ///图片名称
  String? imageName;

  ///图片地址
  String? imageUrl;

  ///电子菜单id
  String? menuId;

  ///热点区域
  String? hotZone;

  ElectronicMenuProduct({this.obxId = 0,this.updateTime =0, this.imageUrl});

  factory ElectronicMenuProduct.fromJson(Map<String, dynamic> json) =>
      _$ElectronicMenuProductFromJson(json);

  Map<String, dynamic> toJson() => _$ElectronicMenuProductToJson(this);

  static ToOne<ElectronicMenuProduct> toOneFromJson(
          Map<String, dynamic> json) =>
      ToOne(target: ElectronicMenuProduct.fromJson(json));

  static Map<String, dynamic>? toOneJson(ToOne<ElectronicMenuProduct> s) =>
      s.target != null ? _$ElectronicMenuProductToJson(s.target!) : {};

  static ToMany<ElectronicMenuProduct> toManyFromJson(List<dynamic>? json) =>
      ToMany(
          items: json?.map((e) => ElectronicMenuProduct.fromJson(e)).toList());

  static List<Map<String, dynamic>>? toManyJson(
          ToMany<ElectronicMenuProduct>? s) =>
      s?.toList().map((e) => e.toJson()).toList();

  @override
  int updateTime;

  @override
  int update(Store store, int? time) {
    updateTime = time?? updateTime;
    var box =  store.box<ElectronicMenuProduct>();
    return box.put(this);
  }
}

@Entity()
@JsonSerializable()
class DishList  with IEntity{
  @Id()
  int obxId;

  ///变价
  double? changePrice;

  ///自定义价格(如果有自定义价格，则使用自定义价格；否则使用原始价格)
  double? customPrice;

  ///最大可选数量
  double? maxAmount;

  ///会员1变价
  double? memberPrice1;

  ///会员2变价
  double? memberPrice2;

  ///会员3变价
  double? memberPrice3;

  ///最小可选数量
  double? minAmount;

  ///自定义菜单的分类的菜品对应的原菜品规格uuid
  String? productSpecsUuid;

  ///排序字段
  int? sort;

  ///自定义菜单的分类的菜品的uuid
  String? uuid;

  @override
  int updateTime ;

  DishList({
    this.obxId = 0,
    this.updateTime  =0,
    this.changePrice,
    this.customPrice,
    this.maxAmount,
    this.memberPrice1,
    this.memberPrice2,
    this.memberPrice3,
    this.minAmount,
    this.productSpecsUuid,
    this.sort,
    this.uuid,
  });

  factory DishList.fromJson(Map<String,dynamic> json) => _$DishListFromJson(json);
  Map<String, dynamic> toJson() => _$DishListToJson(this);

  static ToOne<DishList> toOneFromJson(Map<String, dynamic> json) =>
  ToOne(target: DishList.fromJson(json));

  static Map<String, dynamic>? toOneJson(ToOne<DishList> s) =>
  s.target != null ? _$DishListToJson(s.target!) : {};

  static ToMany<DishList> toManyFromJson(List<dynamic>? json) =>
  ToMany(items: json?.map((e) => DishList.fromJson(e)).toList());

  static List<Map<String, dynamic>>? toManyJson(ToMany<DishList>? s) =>
  s?.toList().map((e) => e.toJson()).toList();

  @override
  int update(Store store,int? time) {
    updateTime = time?? updateTime;
    var box =  store.box<DishList>();
   return box.update(this, DishList_.uuid, uuid);
  }

  @override
  String toString() {
    return 'DishList{obxId: $obxId, customPrice: $customPrice, maxAmount: $maxAmount, productSpecsUuid: $productSpecsUuid}';
  }
}
